/**
 * @file 轨迹控制器
 * @description 处理轨迹相关的请求
 * @author AI Assistant
 * @date 2024-02-20
 * @updated 2024-03-09
 */

import { Controller, Post, Get, Body, Param, Query, UploadedFile, UseInterceptors, ParseIntPipe, Optional } from '@nestjs/common';
import { GpsLogService } from '../services/log-processor.service';
import { TrackService } from '../services/track.service';
import { ApiResponse } from '../../common/dto/api-response.dto';
import { FileInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { extname } from 'path';
import { ApiOperation, ApiParam, ApiQuery, ApiTags, ApiBody } from '@nestjs/swagger';
import { DeviceQueryDto } from '../dto/device-query.dto';
import { DeviceListResponse } from '../interfaces/device.interface';

@ApiTags('轨迹')
@Controller('track')
export class TrackController {
  constructor(
    private readonly gpsLogService: GpsLogService,
    private readonly trackService: TrackService
  ) {}

  /**
   * 处理本地已存在的GPS日志文件
   * @param body 请求体，包含文件路径、设备ID和是否等待完成
   * @returns 处理结果或任务状态
   */
  @ApiOperation({ summary: '处理本地已存在的GPS日志文件' })
  @ApiBody({
    schema: {
      type: 'object',
      required: ['filePath'],
      properties: {
        filePath: {
          type: 'string',
          description: '本地日志文件的路径'
        },
        deviceId: {
          type: 'string',
          description: '设备ID (可选)'
        },
        waitForCompletion: {
          type: 'boolean',
          description: '是否等待任务完成 (默认: false)'
        }
      }
    }
  })
  @Post('process-log')
  async processLocalLogFile(
    @Body() body: { 
      filePath: string; 
      deviceId?: string; 
      waitForCompletion?: boolean 
    }
  ) {
    if (!body.filePath) {
      return ApiResponse.error('未指定文件路径');
    }
    
    const response = await this.gpsLogService.processLogFile(body.filePath, body.deviceId);
    
    // 如果请求要求等待完成，则轮询等待任务完成
    if (body.waitForCompletion && response.success && response.data?.taskId) {
      const taskId = response.data.taskId;
      const maxRetries = 100; // 最大轮询次数
      const pollingInterval = 500; // 轮询间隔(毫秒)
      
      let retries = 0;
      let taskCompleted = false;
      let finalResult;
      
      while (!taskCompleted && retries < maxRetries) {
        // 等待一定时间
        await new Promise(resolve => setTimeout(resolve, pollingInterval));
        
        // 查询任务状态
        const statusResponse = await this.gpsLogService.getTaskStatus(taskId);
        if (statusResponse.success && statusResponse.data) {
          const taskInfo = statusResponse.data;
          
          // 检查任务是否完成
          if (
            taskInfo.status === 'completed' || 
            taskInfo.status === 'failed'
          ) {
            taskCompleted = true;
            finalResult = {
              success: taskInfo.status === 'completed',
              code: taskInfo.status === 'completed' ? 200 : 500,
              message: taskInfo.status === 'completed' ? '日志处理完成' : `日志处理失败: ${taskInfo.error || '未知错误'}`,
              data: {
                ...(taskInfo.stats || {}),
                taskId: taskInfo.taskId,
                deviceId: taskInfo.deviceId,
                duration: taskInfo.endTime && taskInfo.startTime
                  ? (taskInfo.endTime.getTime() - taskInfo.startTime.getTime()) / 1000 
                  : null
              },
              timestamp: Date.now()
            };
          }
        }
        
        retries++;
      }
      
      // 如果任务完成，返回最终结果
      if (taskCompleted && finalResult) {
        return finalResult;
      }
      
      // 如果超时，返回超时信息和当前状态
      return {
        success: false,
        code: 408,
        message: '任务处理超时，请稍后通过任务ID查询结果',
        data: { taskId },
        timestamp: Date.now()
      };
    }
    
    // 如果不需要等待完成，直接返回原始响应
    return response;
  }

  /**
   * 上传并处理GPS日志文件
   * @param file 上传的文件
   * @param deviceId 设备ID
   * @param waitForCompletion 是否等待处理完成
   * @returns 处理结果或任务状态
   */
  @ApiOperation({ summary: '上传并处理GPS日志文件' })
  @ApiQuery({ name: 'deviceId', description: '设备ID (可选)', required: false })
  @ApiQuery({ name: 'waitForCompletion', description: '是否等待任务完成 (默认: false)', required: false, type: 'boolean' })
  @Post('process-log-file')
  @UseInterceptors(
    FileInterceptor('file', {
      storage: diskStorage({
        destination: './uploads/logs',
        filename: (req, file, cb) => {
          const randomName = Array(32)
            .fill(null)
            .map(() => (Math.round(Math.random() * 16)).toString(16))
            .join('');
          cb(null, `${randomName}${extname(file.originalname)}`);
        },
      }),
    }),
  )
  async processLogFile(
    @UploadedFile() file: Express.Multer.File,
    @Query('deviceId') deviceId?: string,
    @Query('waitForCompletion') waitForCompletion?: string,
  ) {
    if (!file) {
      return ApiResponse.error('未上传文件');
    }
    
    const response = await this.gpsLogService.processLogFile(`uploads/logs/${file.filename}`, deviceId);
    
    // 处理等待完成的逻辑，与processLocalLogFile相同
    const shouldWait = waitForCompletion === 'true' || waitForCompletion === '1';
    if (shouldWait && response.success && response.data?.taskId) {
      const taskId = response.data.taskId;
      const maxRetries = 100; // 最大轮询次数
      const pollingInterval = 500; // 轮询间隔(毫秒)
      
      let retries = 0;
      let taskCompleted = false;
      let finalResult;
      
      while (!taskCompleted && retries < maxRetries) {
        // 等待一定时间
        await new Promise(resolve => setTimeout(resolve, pollingInterval));
        
        // 查询任务状态
        const statusResponse = await this.gpsLogService.getTaskStatus(taskId);
        if (statusResponse.success && statusResponse.data) {
          const taskInfo = statusResponse.data;
          
          // 检查任务是否完成
          if (
            taskInfo.status === 'completed' || 
            taskInfo.status === 'failed'
          ) {
            taskCompleted = true;
            finalResult = {
              success: taskInfo.status === 'completed',
              code: taskInfo.status === 'completed' ? 200 : 500,
              message: taskInfo.status === 'completed' ? '日志处理完成' : `日志处理失败: ${taskInfo.error || '未知错误'}`,
              data: {
                ...(taskInfo.stats || {}),
                taskId: taskInfo.taskId,
                deviceId: taskInfo.deviceId,
                duration: taskInfo.endTime && taskInfo.startTime
                  ? (taskInfo.endTime.getTime() - taskInfo.startTime.getTime()) / 1000 
                  : null
              },
              timestamp: Date.now()
            };
          }
        }
        
        retries++;
      }
      
      // 如果任务完成，返回最终结果
      if (taskCompleted && finalResult) {
        return finalResult;
      }
      
      // 如果超时，返回超时信息和当前状态
      return {
        success: false,
        code: 408,
        message: '任务处理超时，请稍后通过任务ID查询结果',
        data: { taskId },
        timestamp: Date.now()
      };
    }
    
    // 如果不需要等待完成，直接返回原始响应
    return response;
  }
  
  /**
   * 获取任务处理状态
   * @param taskId 任务ID
   * @returns 任务处理状态
   */
  @ApiOperation({ summary: '获取任务处理状态' })
  @ApiParam({ name: 'taskId', description: '任务ID' })
  @Get('task-status/:taskId')
  async getTaskStatus(@Param('taskId') taskId: string) {
    return this.gpsLogService.getTaskStatus(taskId);
  }
  
  /**
   * 获取任务列表
   * @param limit 限制返回数量
   * @returns 任务列表
   */
  @ApiOperation({ summary: '获取任务列表' })
  @ApiQuery({ name: 'limit', description: '限制返回数量', required: false })
  @Get('tasks')
  async getTaskList(@Query('limit', new ParseIntPipe({ optional: true })) limit?: number) {
    return this.gpsLogService.getTaskList(limit);
  }
  
  /**
   * 获取坐标过滤统计信息
   * @returns 过滤器统计信息
   */
  @ApiOperation({ summary: '获取坐标过滤统计信息' })
  @Get('filter-stats')
  async getFilterStats() {
    return this.gpsLogService.getFilterStats();
  }

  /**
   * 获取所有设备ID列表
   * @param queryDto 查询参数
   * @returns 设备列表响应
   */
  @ApiOperation({ 
    summary: '获取所有设备ID列表',
    description: '获取系统中所有设备的ID列表，支持状态过滤和关键字搜索，分页操作由前端处理'
  })
  @ApiQuery({ 
    name: 'status', 
    description: '设备状态: -1=全部, 0=离线, 1=在线', 
    required: false, 
    type: Number,
    example: -1
  })
  @ApiQuery({ name: 'keyword', description: '搜索关键字', required: false, type: String })
  @Get('device/list')
  async getAllDeviceIdsList(@Query() queryDto: DeviceQueryDto): Promise<ApiResponse<DeviceListResponse>> {
    return this.gpsLogService.getAllDeviceIdsList(queryDto);
  }

  /**
   * 根据设备ID查询轨迹数据
   * @param deviceId 设备ID
   * @param startTime 开始时间
   * @param endTime 结束时间
   * @returns 轨迹数据
   */
  @ApiOperation({ summary: '根据设备ID查询轨迹数据' })
  @ApiParam({ name: 'deviceId', description: '设备ID' })
  @ApiQuery({ name: 'startTime', description: '开始时间', required: false })
  @ApiQuery({ name: 'endTime', description: '结束时间', required: false })
  @Get(':deviceId')
  async getTracksByDeviceId(
    @Param('deviceId') deviceId: string,
    @Query('startTime') startTime?: string,
    @Query('endTime') endTime?: string,
  ) {
    const filters: Record<string, any> = {};
    
    if (startTime) {
      filters.startTime = new Date(startTime);
    }
    
    if (endTime) {
      filters.endTime = new Date(endTime);
    }
    
    return this.gpsLogService.findByDeviceId(deviceId, filters);
  }
} 